﻿#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QStandardPaths>
#include <QVBoxLayout>
#include <QDebug>
#include <QRegularExpression>

#pragma execution_character_set("utf-8") //支持中文

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    InitUI();

    //通信组件初始化
    client = new TcpClient();
    server = new TcpServer();
    tcpCommon = NULL;
    connect(client, SIGNAL(sendMsgToMain(MesSource,CommonMessage)), this, SLOT(onRecvNewMsg(MesSource,CommonMessage)));
    connect(server, SIGNAL(sendMsgToMain(MesSource,CommonMessage)), this, SLOT(onRecvNewMsg(MesSource,CommonMessage)));

    //定时器
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
    timer->start(100);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::InitUI()
{
    /* 窗口和标题初始化 */
    setWindowTitle("MyPlayer");
    this->setFixedSize(ui->widget_player->width()+300, ui->widget_player->height()+30);

    /* 播放器初始化 */
    QAxWidget* axWidget = new QAxWidget;   //控制WMP
    player = new PlayerController(nullptr, axWidget);
    connect(player, SIGNAL(sendMsgToMain(MesSource,CommonMessage)), this, SLOT(onRecvNewMsg(MesSource,CommonMessage)));
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(axWidget);
    ui->widget_player->setLayout(layout);

    /* 菜单栏初始化 */
    QMenuBar *pMenuBar = this->menuBar();
    QMenu *pMenu_open =  new QMenu("开始",this);
    QAction *pAction_openFile = new QAction("打开文件",this);
    QAction *pAction_fullScreen = new QAction("全屏播放",this);
    QAction *pAction_about = new QAction("关于",this);
    pMenu_open->addAction(pAction_openFile);
    pMenu_open->addAction(pAction_fullScreen);
    pMenu_open->addAction(pAction_about);
    pMenuBar->addMenu(pMenu_open);
    connect(pAction_openFile,&QAction::triggered,this,&MainWindow::onOpenFile);
    connect(pAction_fullScreen,&QAction::triggered,this,&MainWindow::on_btn_FullScreen_clicked);
    connect(pAction_about, &QAction::triggered,[&](void){
        QMessageBox::information(this, "关于", "SyncPlayer_同步播放器\nBy cngo\nhttps://blog.cngo.rr.nu");
    });

    /* 同步和连接相关初始化 */
    ui->ck_sync->setChecked(true);
    ui->btn_Send->setEnabled(false);
    ui->btn_Close->setEnabled(false);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);
    // axWidget->close();
}


void MainWindow::on_btn_FullScreen_clicked()
{
    player->setFullScreen();
}

void MainWindow::on_btn_Send_clicked()
{
    QString str = ui->textEdit_send->toPlainText().toUtf8();
    if(!str.isEmpty() && tcpCommon)
    {
        CommonMessage msg = CommonMessage(SimpleMessage, str);
        tcpCommon->sendMsg(CommonMessage::messageToString(msg));
    }
}

//作为服务端
void MainWindow::on_btn_Listen_clicked()
{
    if(ui->btn_Listen->text() == "开始监听")
    {
        startListenAsServer();
    }
    else
    {
        stopListenAsServer();
    }
}

void MainWindow::startListenAsServer(){
    QString port = ui->lineEdit_ListenPort->text();
    if(!port.contains(QRegularExpression("^\\d+$")))   //检测是否为纯数字
    {
        QMessageBox::information(ui->centralwidget,"警告","监听端口设置有误");
        return;
    }
    bool res = server->listenToConnect(QHostAddress::Any, port.toInt());
    if(res)
    {
        ui->btn_Listen->setText("停止监听");
        ui->lineEdit_ListenPort->setEnabled(false);
        //禁止客户端模式
        ui->tab_client->setEnabled(false);
        QMessageBox::information(ui->centralwidget,"注意","监听成功");
    }
    else
    {
        QMessageBox::information(ui->centralwidget,"注意","监听失败");
    }
}

void MainWindow::stopListenAsServer(){
    server->stopListen();
    ui->btn_Listen->setText("开始监听");
    ui->lineEdit_ListenPort->setEnabled(true);
    ui->tab_client->setEnabled(true);
}

void MainWindow::on_btn_Close_clicked()
{
    bool state = server->closeConnetion();
    if(state){
        disConnectionAsServer();
        stopListenAsServer();
    }
}

void MainWindow::acceptConnectionAsServer(){
    tcpCommon = server;
    ui->textEdit_talk->append("===成功和客户端进行连接===");
    ui->btn_Send->setEnabled(true);
    ui->btn_Listen->setEnabled(false);
    ui->btn_Close->setEnabled(true);
    QMessageBox::information(ui->centralwidget,"注意","连接成功");
}

void MainWindow::disConnectionAsServer(){
    tcpCommon = NULL;
    ui->label_delay->setText("--");
    ui->textEdit_talk->append("===客户端断开连接===");
    ui->btn_Send->setEnabled(false);
    ui->btn_Listen->setEnabled(true);
    ui->btn_Close->setEnabled(false);
    QMessageBox::information(ui->centralwidget,"注意","连接断开");
}

//作为客户端
void MainWindow::on_btn_Connect_clicked()
{
    if(ui->btn_Connect->text() == "开始连接"){
        connectToHostAsClient();
    }else{
        disconnectToHostAsClient();
    }
}

//客户端开始连接
void MainWindow::connectToHostAsClient(){
    QString ip = ui->lineEdit_ServerIP->text();
    qint16 port = ui->lineEdit_ServerPort->text().toInt();
    bool state = client->connectToHost((QHostAddress)ip, port);
    if(state){
        ui->textEdit_talk->append("===成功和服务器进行连接===");
        ui->btn_Connect->setText("断开连接");
        ui->btn_Send->setEnabled(true);
        ui->lineEdit_ServerIP->setEnabled(false);
        ui->lineEdit_ServerPort->setEnabled(false);
        //禁止服务器模式
        ui->tab_server->setEnabled(false);
        tcpCommon = client;
        QMessageBox::information(ui->centralwidget,"注意","连接成功");
    }
    else{
        ui->textEdit_talk->append("===和服务器连接失败===");
        QMessageBox::information(ui->centralwidget,"注意","连接失败");
    }
}
//客户端主动断开
void MainWindow::disconnectToHostAsClient(){
    bool state = client->closeConnetion();
    if (state)
    {
        ui->textEdit_talk->append("===断开连接成功===");
        disConnectionAsClient();
        // QMessageBox::information(ui->centralwidget,"注意","连接断开");
    }
    else
    {
        ui->textEdit_talk->append("===断开连接失败===");
        QMessageBox::information(ui->centralwidget,"注意","断开连接失败");
    }
}

void MainWindow::disConnectionAsClient(){
    ui->btn_Connect->setText("开始连接");
    ui->btn_Send->setEnabled(false);
    ui->lineEdit_ServerIP->setEnabled(true);
    ui->lineEdit_ServerPort->setEnabled(true);
    //服务器模式
    ui->tab_server->setEnabled(true);
    tcpCommon = NULL;
    ui->label_delay->setText("--");
    QMessageBox::information(ui->centralwidget,"注意","连接断开");
}

void MainWindow::on_btn_sync_clicked()
{
    // player->pause();
    // QString pos = player->getProcessBarInfo();
    // // if(tcpCommon){
    // //     tcpCommon->sendMsg(); //).toUtf8().data()
    // // }
    // ui->label_mytime->setText(pos);
}

void MainWindow::onOpenFile(){
    QString dirPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    QString filter = "mp4文件(*.mp4);;mp3文件(*.mp3);;wmv文件(*.wmv);;所有文件(*.*)"; //文件过滤器
    QString path = QFileDialog::getOpenFileName(this, "选择要播放的文件", dirPath, filter);
    if (path.isEmpty()) return;
    player->openFile(path);
    MediaInfo info = player->getCurrentMediaInfo();
    setWindowTitle(info.title);
    ui->label_title->setText(info.title);
    ui->label_myduration->setText(info.duration);
}

//100ms定时器
void MainWindow::onTimeOut(){
    static int count = 0;
    static int lastPos = 0;

    static bool flag = true;
    static QString title = "";
    static QString duration = "";

    if(player->getPlayState() != IDLE){
        QString pos = player->getProcessBarInfo();
        int nowPos = (int)pos.toDouble();
        if(nowPos != lastPos){
            lastPos = nowPos;
            ui->label_mytime->setText(PlayerController::timeToString(pos));
            if(tcpCommon && ui->ck_sync->isChecked()){
                CommonMessage msg = CommonMessage(PlayerProgess, pos);
                tcpCommon->sendMsg(CommonMessage::messageToString(msg));
            }
        }

        //发送视频信息
        MediaInfo info = player->getCurrentMediaInfo();
        if(info.title.compare(title) || info.duration.compare(duration)){
            title = info.title;
            duration = info.duration;
            ui->label_myduration->setText(PlayerController::timeToString(duration));
            flag = true;
        }
        if(tcpCommon && flag){
            CommonMessage msg = CommonMessage(PlayerMediaInfo, title + ";;" + duration);
            tcpCommon->sendMsg(CommonMessage::messageToString(msg));
            flag = false;
        }
    }

    // 3s发送一次心跳包
    if(tcpCommon && count % 30 == 0){
        CommonMessage msg = CommonMessage(HeartBeat, "NONE");
        tcpCommon->sendMsg(CommonMessage::messageToString(msg));
    }


    count += 1;
}

void MainWindow::onRecvNewMsg(MesSource source, CommonMessage msg){
    // 本地播放器发来的消息
    if(source == LocalPlayer){
        switch(msg.type){
            case PlayerStateChange:
                ui->label_mystate->setText(PlayerController::stateToString(msg.msg));
                if(tcpCommon && ui->ck_sync->isChecked()){
                    tcpCommon->sendMsg(CommonMessage::messageToString(msg));
                }
                break;
            case PlayerProgessChange:
                ui->label_mytime->setText(PlayerController::timeToString(msg.msg));
                if(tcpCommon && ui->ck_sync->isChecked()){
                    tcpCommon->sendMsg(CommonMessage::messageToString(msg));
                }
                break;
            case PlayerMediaInfo:
                qDebug() << "本地播放器打开视频" << msg.msg;
                qDebug() << msg.msg;
                if(tcpCommon && ui->ck_sync->isChecked()){
                    tcpCommon->sendMsg(CommonMessage::messageToString(msg));
                }
                break;
            default:
                qDebug() << "未知类型的本地消息" << msg.type << " " << msg.timestamp << " " << msg.msg;
                break;
        }
    }
    // 对端发来的消息
    else{
        switch(msg.type){
            case PlayerStateChange:
                // qDebug() << "对方播放器状态改变" << msg.msg;
                ui->label_state->setText(PlayerController::stateToString(msg.msg));
                if(ui->ck_sync->isChecked()){
                    PlayerState state = (PlayerState) msg.msg.toInt();
                    bool ok = player->setPlayState(state);
                }
                break;
            case PlayerProgessChange:
                if(ui->ck_sync->isChecked()){
                    player->setCurrentPosition(msg.msg);
                }
                break;
            case PlayerMediaInfo:
                setPeerMediaInfo(msg.msg);
                break;
            case PlayerProgess:
                ui->label_time->setText(PlayerController::timeToString(msg.msg));
                break;
            case HeartBeat:
                ui->label_delay->setText(QString::number(QDateTime::currentMSecsSinceEpoch() - msg.timestamp)+"ms");
                break;
            case SimpleMessage:
                printCommonLog("Peer:"+msg.msg);
                break;
            case NewConnection:
                acceptConnectionAsServer();
                printCommonLog("监听到客户端连接");
                break;
            case DisConnection:
                if(tcpCommon == server){
                    disConnectionAsServer();
                }else if(tcpCommon == client){
                    disConnectionAsClient();
                }
                printCommonLog("和对方的连接断开");
                break;
            case ErrConnection:
                QMessageBox::information(this, "Other Connect Error", msg.msg);
                break;
            default:
                qDebug() << "未知类型的对方消息" << msg.type << " " << msg.timestamp << " " << msg.msg;
                break;
        }
    }
}

void MainWindow::printCommonLog(QString log, QString type){
    QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    ui->textEdit_talk->append(time + " " + type + " " + log);
}

void MainWindow::setPeerMediaInfo(QString msg){
    QList<QString> lst = msg.split(";;");
    ui->label_title->setText(lst[0]);
    ui->label_duration->setText(PlayerController::timeToString(lst[1]));
    printCommonLog("对方播放器打开视频：" + lst[0]);
}

